package com.example.java_gobang.api;

import com.example.java_gobang.game.*;
import com.example.java_gobang.model.User;
import com.example.java_gobang.model.UserMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;

@Component
public class GameAPI extends TextWebSocketHandler {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RoomManager roomManager;
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private UserMapper userMapper;
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //获取用户的身份信息
        GameReadyResponse response = new GameReadyResponse();
        User user = (User) session.getAttributes().get("user");

        if (user == null){
            response.setOk(false);
            response.setReason("用户尚未登录");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        //判断当前用户是否已经进入房间
        Room room = roomManager.getRoomByUserId(user.getUserId());
        if (room == null){
            response.setOk(false);
            response.setReason("用户尚未匹配到");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        //判断用户有没有多开
        if (onlineUserManager.getFromGameHall(user.getUserId()) != null
        || onlineUserManager.getFromGameRoom(user.getUserId()) !=null){
            response.setOk(false);
            response.setReason("禁止多开游戏");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            return;
        }
        //玩家进入游戏房间(玩家此时已经跳转页面成功）
        onlineUserManager.enterGameRoom(user.getUserId(), session);//设置玩家上线
        synchronized (room){


        if (room.getUser1() == null){
            room.setUser1(user);
            //把玩家1作为白子
            room.setWhiteUser(user.getUserId());
            System.out.println("玩家"+user.getUsername()+"已经准备就绪！作为玩家1");
            return;
        }
        if (room.getUser2() == null){
            room.setUser2(user);
            System.out.println("玩家"+user.getUsername()+"已经准备就绪！作为玩家2");
            //两个玩家都就绪，服务器要给两个玩家都返回 websocket 响应
            noticeGameReady(room,room.getUser1(),room.getUser2());
            noticeGameReady(room,room.getUser2(),room.getUser1());
        }
    }
        // 房间已经满了!
        response.setOk(false);
        String log = "roomId=" + room.getRoomId() + " 已经满了! 连接游戏失败!";
        response.setReason(log);
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        System.out.println(log);


    }

    private void noticeGameReady(Room room, User thisuser, User thatuser) {
        GameReadyResponse response = new GameReadyResponse();
        response.setMessage("gameReady");
        response.setOk(true);
        response.setReason("");
        response.setRoomId(room.getRoomId());
        response.setThisUserId(thisuser.getUserId());
        response.setThatUserId(thatuser.getUserId());
        response.setWhiteUser(room.getWhiteUser());
        WebSocketSession session1 = onlineUserManager.getFromGameRoom(thisuser.getUserId());
        try {
            session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //获取用户身份信息
        User user = (User) session.getAttributes().get("user");
        if (user == null){
            return;
        }
        //获取房间对象
        Room room = roomManager.getRoomByUserId(user.getUserId());
        //通过room对象处理具体的请求
        room.putChess(message.getPayload());

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if (user == null){
            return;
        }
        WebSocketSession existSession = onlineUserManager.getFromGameRoom(user.getUserId());
        if (existSession != session){
            System.out.println("当前的会话不是玩家游戏中的会话, 不做处理!");
            return;
        }
        System.out.println("连接出错！ userId="+user.getUserId());
        onlineUserManager.exitGameRoom(user.getUserId());
        noticeThatUserWin(user);

    }

    private void noticeThatUserWin(User user) throws IOException {
        //找到玩家所在房间
        Room room = roomManager.getRoomByUserId(user.getUserId());
        if (room == null){
            System.out.println("当前房间已经释放，无需通知对手");
            return;
        }
        //根据房间找到对手
        User thatUser = (user == room.getUser1()) ? room.getUser2() : room.getUser1();
        //找到对手的在线状态
        WebSocketSession webSocketSession = onlineUserManager.getFromGameRoom(thatUser.getUserId());
        if (webSocketSession == null) {
            // 这就意味着对手也掉线了!
            System.out.println("对手也已经掉线了, 无需通知!");
            return;
        }
        //构造一个响应, 来通知对手, 你是获胜方
        GameResponse resp = new GameResponse();
        resp.setMessage("putChess");
        resp.setUserId(thatUser.getUserId());
        resp.setWinner(thatUser.getUserId());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));

        //更新玩家的分数信息
        int winUserId = thatUser.getUserId();
        int loseUserId = user.getUserId();
        userMapper.userWin(winUserId);
        userMapper.userLose(loseUserId);

        // 释放房间对象
        roomManager.remove(room.getRoomId(), room.getUser1().getUserId(), room.getUser2().getUserId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        User user = (User) session.getAttributes().get("user");
        if (user == null){
            return;
        }
        WebSocketSession existSession = onlineUserManager.getFromGameRoom(user.getUserId());
        if (existSession != session){
            System.out.println("当前的会话不是玩家游戏中的会话, 不做处理!");
            return;
        }
        System.out.println("用户退出！ userId="+user.getUserId());
        onlineUserManager.exitGameRoom(user.getUserId());
        noticeThatUserWin(user);

    }
}
